package com.hyny.framework.platform.system.service.impl;


import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.hyny.framework.base.redis.RedisEnum;
import com.hyny.framework.base.redis.RedisUtil;
import com.hyny.framework.platform.system.entity.param.LoginParam;
import com.hyny.framework.platform.system.entity.pojo.SysUser;
import com.hyny.framework.platform.system.entity.pojo.SysUserRole;
import com.hyny.framework.platform.system.entity.pojo.SysRoleMenu;

import com.hyny.framework.platform.system.entity.vo.LoginVO;
import com.hyny.framework.platform.system.service.*;
import com.hyny.framework.platform.system.utils.bean.Result;
import com.hyny.framework.utils.IpUtil;
import com.hyny.framework.utils.WebUtil;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class LoginServiceImpl implements ILoginService {

    /**
     * Redis工具类
     */
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;


    /**
     * 过期时间
     */
    @Value("${hyny.jwt.expiration}")
    private Long expiration;
    /**
     * 加密用的盐
     */
    @Value("${hyny.jwt.salt}")
    private String salt;

    @Override
    public Result login(LoginParam loginParam) {
        sysUserService.list();
        // 进行用户认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginParam.getUserName(), loginParam.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//        // 获取用户信息
        LoginVO loginUser = (LoginVO) authenticate.getPrincipal();

        // 将用户登录信息存入缓存
        redisUtil.setStringExpire(RedisEnum.LOGIN_INFO ,loginUser.getUser().getId().toString(), JSONObject.toJSONString(loginUser), expiration);

        // 更新用户登录信息
        sysUserService.update(new LambdaUpdateWrapper<SysUser>()
                .eq(SysUser::getId,loginUser.getUser().getId())
                .set(SysUser::getLoginIp, IpUtil.getIpAddr(WebUtil.getRequest()))
                .set(SysUser::getLoginDate,new Date())
        );


        // 生成JWT
        Map<String, Object> claimsMap = new HashMap<>();
        claimsMap.put("userId", loginUser.getUser().getId());
        claimsMap.put("userName", loginUser.getUser().getUserName());
        JwtBuilder jwtBuilder = Jwts.builder()
                .setSubject("gs") // 签发人
                .setIssuedAt(new Date()) // 签发日期
                .setClaims(claimsMap) // 自定义信息
                .setExpiration(DateUtil.offset(new Date(), DateField.SECOND,expiration.intValue()) ) // 超时时间
                .signWith(SignatureAlgorithm.HS256, salt); // 加密规则

        return Result.ok("登录成功", jwtBuilder.compact());


    }
    @Override
    public void logoutUser(Long userId) {
        redisUtil.removeString(RedisEnum.LOGIN_INFO, userId.toString());
    }

    @Override
    public void logoutRole(Long roleId) {
        List<SysUserRole> userRoleList=sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId,roleId));
        for (SysUserRole userRole:userRoleList) {
            logoutUser( userRole.getUserId());
        }
    }

    @Override
    public void logoutMenu(Long menuId) {
        List<SysRoleMenu> sysRoleMenus=sysRoleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getMenuId,menuId));
        for (SysRoleMenu roleMenu:sysRoleMenus) {
            List<SysUserRole> userRoleList=sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId,roleMenu.getRoleId()));
            for (SysUserRole userRole:userRoleList) {
                logoutUser( userRole.getUserId());
            }
        }
    }



}